package config

import (
	"math/rand"

	"github.com/spf13/viper"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
)

var (
	AppName    string // 项目名称
	Debug      bool   // 当前模式
	Logger     *zap.Logger
	ServerPort string // 服务监听端口

	FrontPath   string // 前端路径
	ManagerPath string // 管理路径

	AdminUsername string // 登录用户名
	AdminPassword string // 登录密码

	TokenSecret        string // token salt
	TokenExpiredSecond int    // token 过期时间

	DatabaseType string // 数据库类型:mysql,sqlite,postgresql

	MysqlUser string
	MysqlPass string
	MysqlHost string
	MysqlPort string
	MysqlName string

	PostgresqlUser string
	PostgresqlPass string
	PostgresqlHost string
	PostgresqlPort string
	PostgresqlName string
)

func init() {
	viper.SetConfigName("config")
	viper.SetConfigType("toml")
	viper.AddConfigPath(".")
	viper.SetDefault("app_name", "webstack")
	viper.SetDefault("debug", false)
	viper.SetDefault("token_secret", genRandomString(22))
	viper.SetDefault("token_expired_second", 99600)
	viper.SetDefault("server_port", ":50000")
	viper.SetDefault("database_type", "sqlite")
	viper.SetDefault("mysql", map[string]string{"user": "root", "pass": "root", "host": "127.0.0.1", "port": "3306", "dbname": "_"})
	viper.SetDefault("postgresql", map[string]string{"user": "root", "pass": "root", "host": "localhost", "port": "9920", "dbname": "_"})
	viper.SetDefault("admin_username", "admin")
	viper.SetDefault("admin_password", "admin")
	viper.SetDefault("front_path", "./front_dist")
	viper.SetDefault("manager_path", "./manager_dist")

	if err := viper.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); ok {
			viper.SafeWriteConfig()
		}
	}

	Debug = viper.GetBool("debug")

	AppName = viper.GetString("app_name")
	ServerPort = viper.GetString("server_port")
	AdminUsername = viper.GetString("admin_username")
	AdminPassword = viper.GetString("admin_password")
	FrontPath = viper.GetString("front_path")
	ManagerPath = viper.GetString("manager_path")

	TokenSecret = viper.GetString("token_secret")
	TokenExpiredSecond = viper.GetInt("token_expired_second")

	tmpMysql := viper.GetStringMapString("mysql")
	MysqlUser = tmpMysql["user"]
	MysqlPass = tmpMysql["pass"]
	MysqlHost = tmpMysql["host"]
	MysqlPort = tmpMysql["port"]
	MysqlName = tmpMysql["dbname"]

	tmpPostgre := viper.GetStringMapString("postgresql")
	PostgresqlUser = tmpPostgre["user"]
	PostgresqlPass = tmpPostgre["pass"]
	PostgresqlHost = tmpPostgre["host"]
	PostgresqlPort = tmpPostgre["port"]
	PostgresqlName = tmpPostgre["dbname"]

	DatabaseType = viper.GetString("database_type")
	if MysqlName == "_" {
		MysqlName = AppName
	}
	if PostgresqlName == "_" {
		PostgresqlName = AppName
	}

	logEncoder := getEncoder()
	logWriter := getWriteSync()

	core := zapcore.NewCore(logEncoder, logWriter, zapcore.InfoLevel)
	Logger = zap.New(core)
}

// 负责设置 encoding 的日志格式
func getEncoder() zapcore.Encoder {
	encoderConfig := zap.NewProductionEncoderConfig()
	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
	encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder

	return zapcore.NewConsoleEncoder(encoderConfig)
}

// 负责日志写入的位置
func getWriteSync() zapcore.WriteSyncer {
	lumberJackLogger := &lumberjack.Logger{
		Filename:   "./logs/log.txt",
		MaxSize:    10,
		MaxBackups: 50,
		MaxAge:     30,
		Compress:   false,
	}
	jackLogger := zapcore.AddSync(lumberJackLogger)

	// syncConsole := zapcore.AddSync(os.Stderr) // 写入到标准输出
	return zapcore.NewMultiWriteSyncer(jackLogger)
}

func genRandomString(n int) string {
	letters := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_+{}[]|\\:;.,<>?")
	b := make([]rune, n)
	for i := range b {
		b[i] = letters[rand.Intn(len(letters))]
	}
	return string(b)
}
